package org.abc.fund.service.funds;

import org.abc.fund.dto.FundBasicInfoDTO;
import org.abc.fund.dto.FundManagerDTO;
import org.abc.fund.entity.funds.FundBasicInfo;
import org.abc.fund.entity.funds.FundManager;
import org.abc.fund.entity.funds.FundTagRelation;
import org.abc.fund.repository.funds.FundBasicInfoRepository;
import org.abc.fund.repository.funds.FundManagerRepository;
import org.abc.fund.repository.funds.FundTagRelationRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class FundManagerService {

  private final FundManagerRepository fundManagerRepository;

  private final FundBasicInfoRepository fundBasicInfoRepository;

  private final FundTagRelationRepository fundTagRelationRepository;

  public FundManagerService(
      FundManagerRepository fundManagerRepository,
      FundBasicInfoRepository fundBasicInfoRepository,
      FundTagRelationRepository fundTagRelationRepository) {
    this.fundManagerRepository = fundManagerRepository;
    this.fundBasicInfoRepository = fundBasicInfoRepository;
    this.fundTagRelationRepository = fundTagRelationRepository;
  }

  // ✅ 获取所有基金经理（可选名称模糊搜索）
  public List<FundManager> getAllManagers(String name) {
    if (name != null && !name.isBlank()) {
      return fundManagerRepository.findByNameContaining(name);
    }
    return fundManagerRepository.findAll();
  }

  // ✅ 分页获取基金经理（DTO 扁平化结构）
  public Page<FundManagerDTO> getManagersDTOByPage(int page, int size, String keyword) {
    Pageable pageable = PageRequest.of(page, size, Sort.by("name").ascending());
    Page<FundManager> managerPage =
        (keyword == null || keyword.isBlank())
            ? fundManagerRepository.findAll(pageable)
            : fundManagerRepository.findByNameContainingIgnoreCase(keyword, pageable);

    List<FundManagerDTO> dtoList =
        managerPage.getContent().stream()
            .map(
                manager ->
                    new FundManagerDTO(
                        manager.getId(),
                        manager.getName(),
                        manager.getIntro(),
                        manager.getFunds() != null ? manager.getFunds().size() : 0,
                        manager.getCompany() != null ? manager.getCompany().getName() : "",
                        null // 基金列表暂不加载
                        ))
            .toList();

    return new PageImpl<>(dtoList, pageable, managerPage.getTotalElements());
  }

  // ✅ 根据标签筛选基金经理（返回 DTO）
  public List<FundManagerDTO> getManagersByTags(List<String> tagNames) {
    if (tagNames == null || tagNames.isEmpty()) {
      return fundManagerRepository.findAll().stream().map(this::toDTO).toList();
    }

    // 找出所有基金代码（含标签）
    List<FundTagRelation> relations = fundTagRelationRepository.findByTagNameIn(tagNames);
    Set<String> fundCodes =
        relations.stream().map(FundTagRelation::getFundCode).collect(Collectors.toSet());

    if (fundCodes.isEmpty()) return List.of();

    // 找出这些基金并提取经理
    List<FundBasicInfo> funds = fundBasicInfoRepository.findByCodeIn(new ArrayList<>(fundCodes));

    // 映射出唯一的经理
    Set<FundManager> managers =
        funds.stream()
            .map(FundBasicInfo::getManager)
            .filter(Objects::nonNull)
            .collect(Collectors.toSet());

    return managers.stream().map(this::toDTO).toList();
  }

  // ✅ 获取某位经理管理的基金（用于表格展开）
  public List<FundBasicInfoDTO> getFundsByManagerName(String managerName) {
    List<FundBasicInfo> funds = fundBasicInfoRepository.findByManager_NameContaining(managerName);
    return funds.stream().map(this::toFundDTO).collect(Collectors.toList());
  }

  // ✅ 获取经理详情（含基金列表）
  public FundManagerDTO getManagerDetail(Long id) {
    FundManager manager = fundManagerRepository.findById(id).orElse(null);
    if (manager == null) return null;
    return toDTO(manager);
  }

  // ➕ 添加经理
  public FundManager addManager(FundManager manager) {
    return fundManagerRepository.save(manager);
  }

  // ✏️ 修改经理
  public FundManager updateManager(Long id, FundManager updated) {
    return fundManagerRepository
        .findById(id)
        .map(
            manager -> {
              manager.setName(updated.getName());
              manager.setIntro(updated.getIntro());
              manager.setFundCount(updated.getFundCount());
              manager.setCompany(updated.getCompany());
              return fundManagerRepository.save(manager);
            })
        .orElse(null);
  }

  // ❌ 删除经理
  public void deleteManager(Long id) {
    fundManagerRepository.deleteById(id);
  }

  // 🔍 获取单个实体（原始实体对象）
  public FundManager getManagerById(Long id) {
    return fundManagerRepository.findById(id).orElse(null);
  }

  // ✅ 私有工具方法：实体转 DTO
  private FundManagerDTO toDTO(FundManager manager) {
    String companyName = manager.getCompany() != null ? manager.getCompany().getName() : "";

    List<FundBasicInfoDTO> fundDTOs =
        manager.getFunds() != null
            ? manager.getFunds().stream().map(this::toFundDTO).toList()
            : List.of();

    return new FundManagerDTO(
        manager.getId(),
        manager.getName(),
        manager.getIntro(),
        manager.getFunds() != null ? manager.getFunds().size() : 0,
        companyName,
        fundDTOs);
  }

  // ✅ 私有工具方法：基金转 DTO
  private FundBasicInfoDTO toFundDTO(FundBasicInfo f) {
    return new FundBasicInfoDTO(
        f.getCode(),
        f.getName(),
        f.getType(),
        f.getStatus(),
        f.getLatestNav(),
        f.getLatestNavDate(),
        f.getLatestEstNav(),
        f.getLatestEstRate(),
        f.getManager() != null ? f.getManager().getName() : "",
        f.getCompany() != null ? f.getCompany().getName() : "");
  }
}
